<script lang="ts">
import { logout, type UserInfo, getUserInfoById, setUserRole, updateUserBio, deleteUser } from '@/api/auth/auth';
import { Component, Inject, Vue, Watch } from 'vue-facing-decorator';
import UserTag from '../component/UserTag.vue';
import TextEditor from '@/components/editor/TextEditor.vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { uploadFile } from '@/util/fileUtil';
import { uploadUserAvatar } from '@/api/auth/auth';

@Component({
  components: {
    UserTag,
    TextEditor,
  },
})
export default class UserPage extends Vue {
  @Inject() userInfo!: UserInfo;
  @Inject() updateLoginInfo!: () => Promise<void>;
  get userId() {
    return +(this.$route.params.id + '');
  }
  get isCurrentUser() {
    return +this.userId === this.userInfo?.id;
  }

  pageUserInfo: UserInfo | null | undefined = void 0;
  async initPageUserInfo() {
    const resp = await getUserInfoById(this.userId);
    if (resp.error) {
      this.pageUserInfo = null;
    } else {
      this.pageUserInfo = resp.data;
    }
  }
  @Watch('userId')
  onUserIdChange() {
    this.pageUserInfo = null;
    this.initPageUserInfo();
  }

  editBio: boolean = false;
  startEditBio() {
    this.editBio = true;
  }
  async cancelEditBio() {
    await this.initPageUserInfo();
    this.editBio = false;
  }
  async submitEditBio() {
    if (!this.pageUserInfo) return;
    const resp = await updateUserBio(this.pageUserInfo.bio);
    if (resp.error) {
      ElMessage({ type: 'error', message: resp.error });
      return;
    }
    this.pageUserInfo = resp.data;
    this.editBio = false;
  }

  async uploadAvatar() {
    const file = await uploadFile('image/*');
    const resp = await uploadUserAvatar(file);
    if (resp.error != null) {
      ElMessage({ type: 'error', message: resp.error });
      return;
    }
    this.pageUserInfo = resp.data;
    if (resp.data.id === this.userInfo?.id) {
      this.updateLoginInfo();
    }
  }

  get avatarUrl() {
    if (this.pageUserInfo?.avatar) {
      return '/api/image/' + this.pageUserInfo.avatar;
    }
    return './img/avatar.png';
  }

  async toggleUserModRole() {
    if (!this.pageUserInfo) return;
    const role = this.pageUserInfo.role === 'user' ? 'mod' : 'user';
    const resp = await setUserRole(this.pageUserInfo.id, role);
    if (resp.error) {
      ElMessage({ type: 'error', message: resp.error });
    }
    this.initPageUserInfo();
  }

  async handleDeleteUser() {
    if (!this.pageUserInfo) return;

    const cont = await ElMessageBox.confirm(
      `确定要删除用户 "${this.pageUserInfo.name}" 吗？此操作不可恢复。`,
      '删除用户', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }).then(() => true, () => false);
    if (!cont) return;

    const resp = await deleteUser(this.pageUserInfo.id);

    if (resp.error) {
      ElMessage({ type: 'error', message: resp.error });
      return;
    }

    ElMessage({ type: 'success', message: '用户已删除' });
    this.$router.push('/');
  }

  get mayDeleteUser() {
    if (!this.userInfo || !this.pageUserInfo) return false;
    if (!['admin', 'mod'].includes(this.userInfo.role)) return false;
    if (this.userInfo.role === 'mod' && this.pageUserInfo.role === 'admin') return false;
    if (this.isCurrentUser) return false;
    return true;
  }

  get maySetModRole() {
    if (!this.userInfo || !this.pageUserInfo) return false;
    if (!['admin'].includes(this.userInfo.role)) return false;
    if (this.pageUserInfo.role === 'admin') return false;
    if (this.isCurrentUser) return false;
    return true;
  }

  async logout() {
    await logout();
    await this.updateLoginInfo();
  }

  mounted() {
    this.initPageUserInfo();
  }

}
</script>
<template>
<div class="profile-page">
  <div class="profile" v-if="pageUserInfo">
    <div class="avatar">
      <div class="avatar-container">
        <img :src="avatarUrl" @click="isCurrentUser && uploadAvatar()" alt="" />
        <el-button v-if="isCurrentUser" class="upload-avatar-button" icon="el-icon-picture" @click="uploadAvatar">上传头像</el-button>
      </div>
    </div>
    <div class="info">
      <div class="username-row">
        <el-button class="logout-button" icon="el-icon-user" v-if="isCurrentUser" @click="logout">退出登录</el-button>
        <el-dropdown class="admin-button" placement="bottom-end" v-if="mayDeleteUser || maySetModRole">
          <el-button icon="el-icon-more"></el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item v-if="maySetModRole && pageUserInfo.role === 'user'" @click="toggleUserModRole">设为 Mod</el-dropdown-item>
              <el-dropdown-item v-if="maySetModRole && pageUserInfo.role === 'mod'" @click="toggleUserModRole">取消设为 Mod</el-dropdown-item>
              <el-dropdown-item v-if="mayDeleteUser" divided @click="handleDeleteUser"><span class="danger-item">删除用户</span></el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <div class="username-title">
          <span class="username">{{ pageUserInfo.name }}</span>
          <user-tag :role="pageUserInfo.role" v-if="pageUserInfo.role !== 'user'" />
        </div>
      </div>
    </div>
    <div class="bio">
      <el-button class="bio-button" v-if="isCurrentUser && !editBio" icon="el-icon-edit" @click="startEditBio">编辑</el-button>
      <el-button class="bio-button" v-if="isCurrentUser && editBio" icon="el-icon-check" @click="submitEditBio">保存</el-button>
      <el-button class="bio-button" v-if="isCurrentUser && editBio" icon="el-icon-close" @click="cancelEditBio">取消</el-button>
      <span class="bio-title">个人简介</span>
      <text-editor v-if="!editBio && pageUserInfo.bio" :model-value="pageUserInfo.bio" readonly />
      <div v-if="!editBio && !pageUserInfo.bio" class="empty-bio">暂无内容</div>
      <text-editor v-if="editBio" v-model="pageUserInfo.bio" />
    </div>
  </div>
</div>
</template>
<style scoped>
.profile-page {
  max-width: 1000px;
  margin: 20px auto;
  padding: 0 20px;
  background-color: var(--el-bg-color-overlay);
  color: var(--el-text-color-primary);
  display: flow-root;
}
.tiny-mode .profile-page {
  padding: 0 10px;
}

.user-tag {
  position: relative;
  top: 0.4em;
}

.info {
  flex: 1;
}

.profile {
  display: grid;
  gap: 10px;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas: "avatar info" "avatar bio";
}

.thin-mode .profile {
  grid-template-areas: "avatar info" "bio bio";
}

.profile .username {
  font-size: 150%;
  font-weight: bold;
  margin-right: 0.5em;
}

.username-row {
  margin-bottom: 20px;
  display: flow-root;
}

.username-title {
  display: flex;
}

.admin-button,
.logout-button {
  float: right;
}

.thin-mode .admin-button,
.thin-mode .logout-button {
  float: none;
  display: block;
  margin-bottom: 10px;
}

.avatar {
  grid-area: avatar;
  position: relative;
}

.avatar-container {
  position: relative;
}

.avatar img {
  width: 300px;
  height: 300px;
}

.thin-mode .avatar img {
  width: 100px;
  height: 100px;
}

.avatar .upload-avatar-button {
  position: absolute;
  left: 50%;
  bottom: 20px;
  margin: 0 auto;
  transform: translateX(-50%);
  background: var(--el-bg-color);
}

.thin-mode .avatar .upload-avatar-button {
  bottom: 0;
}

.avatar:not(:hover):not(:focus-within) .upload-avatar-button {
  visibility: hidden;
}

.info {
  grid-area: info;
}

.bio {
  grid-area: bio;
}

.bio-title {
  display: block;
  font-size: 120%;
  font-weight: bold;
  margin-bottom: 10px;
  line-height: 30px;
}

.bio-button {
  float: right;
}

.empty-bio {
  color: var(--el-text-color-secondary);
}

.danger-item {
  color: var(--el-color-danger);
}

.danger-item:hover {
  background-color: var(--el-color-danger-light-9);
}

</style>
